﻿Imports System.IO
Imports System.Collections.ObjectModel
Imports SqlAnalyzer
Imports System.Data.SqlClient
Imports Microsoft.Win32

Class MainWindow
    Private Shared ActiveConnectionString As String = ""
    Private WithEvents connections As New EntityList(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\sql_appifier_connections.db")
    Private WithEvents querys As New EntityList(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\sql_appifier_queries.db")
    Private UIMetaData As New Hashtable

    Private Sub EditQuery_Click(sender As Object, e As RoutedEventArgs)

    End Sub

    Private Sub QueryDelete_Click(sender As Object, e As RoutedEventArgs)

    End Sub

    Private Sub ConnectionDelete_Click(sender As Object, e As RoutedEventArgs)

    End Sub

    Private Sub NewConnection_Click(sender As Object, e As RoutedEventArgs)
        Dim dlg As New SQL_Connection_Dialog.SQL_Connection_Dialog

        If dlg.ShowDialog(New Wpf32Window(Me)) = Forms.DialogResult.OK Then
            connections.Add(dlg.Server, dlg.ConnectionString)
        End If
    End Sub

    Public Sub ConnectionsEntities_Changed() Handles connections.Changed
        Dim connectionListSource As ObservableCollection(Of Entity) = New ObservableCollection(Of Entity)(From c In connections.Entities Select c)
        connectionList.ItemsSource = connectionListSource
    End Sub

    Private Sub connectionList_SelectionChanged(sender As Object, e As SelectionChangedEventArgs)
        If IsNothing(connectionList.SelectedItem) Then Exit Sub

        Try
            SqlConnectionContext.Current.Close()
            SqlConnectionContext.Current.Dispose()
        Catch ex As Exception
        Finally
            SqlConnectionContext.Current = New SqlConnection(connectionList.SelectedItem.Contents)
            SqlConnectionContext.Current.Open()
        End Try
    End Sub

    Private Sub queryList_SelectionChanged(sender As Object, [event] As SelectionChangedEventArgs)
        If IsNothing(queryList.SelectedItem) Then Exit Sub
        If IsNothing(connectionList.SelectedItem) Then Exit Sub

        If SqlConnectionContext.Current.State <> System.Data.ConnectionState.Open Then Exit Sub

        ClearDynamicForm()

        Dim analyzer As New SqlAnalyzer.SqlAnalyzer(queryList.SelectedItem.Contents)

        Dim gp As New Grid

        gp.ColumnDefinitions.Add(New ColumnDefinition With {.Width = GridLength.Auto})
        gp.ColumnDefinitions.Add(New ColumnDefinition With {.Width = New GridLength(1, GridUnitType.Star)})
        gp.Width = 350
        gp.Height = Double.NaN

        Dim rowNumber As Integer = 0
        For Each variableName As String In analyzer.DeclaredVariableNames
            gp.RowDefinitions.Add(New RowDefinition With {.Height = GridLength.Auto})
            Dim label As New Label

            label.Content = If(analyzer(variableName).UIAttribute.Label, variableName)
            label.VerticalAlignment = Windows.VerticalAlignment.Center
            Grid.SetColumn(label, 0)
            Grid.SetRow(label, rowNumber)

            gp.Children.Add(label)

            Dim variable As DeclaredVariable = analyzer(variableName)
            Dim variableNameWithoutAt As String = variableName.Substring(1, variableName.Length - 1)
            UIMetaData.Add(variableNameWithoutAt, New List(Of KeyValuePair(Of String, Object)))

            Select Case variable.UIAttribute.AttributeType
                Case UIAttributeEnumeration.SqlDropDown, UIAttributeEnumeration.DropDown
                    Dim input As New ComboBox
                    input.ItemsSource = New ObservableCollection(Of KeyValuePair(Of String, Object))(CType(variable.UIAttribute.AttributeData, List(Of KeyValuePair(Of String, Object))))
                    input.DisplayMemberPath = "key"
                    input.DisplayMemberPath = "Text"
                    input.IsSynchronizedWithCurrentItem = True
                    input.Name = variableNameWithoutAt
                    input.VerticalAlignment = Windows.VerticalAlignment.Center
                    input.Margin = New Thickness(0, 0, 5, 0)
                    Grid.SetColumn(input, 1)
                    Grid.SetRow(input, rowNumber)
                    gp.Children.Add(input)
                    QueryForm.RegisterName(input.Name, input)
                Case Else
                    Select Case variable.FrameworkType
                        Case GetType(Integer)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.IntegerBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.NumbersOnly)).Text = variable.DefaultValue
                        Case GetType(Long)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.LongBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.NumbersOnly)).Text = variable.DefaultValue
                        Case GetType(Decimal)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.DecimalBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.DecimalOnly)).Text = variable.DefaultValue
                        Case GetType(Double)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.DoubleBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.DecimalOnly)).Text = variable.DefaultValue
                        Case GetType(Single)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.SingleBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.DecimalOnly)).Text = variable.DefaultValue
                        Case GetType(Byte)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.ByteBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.NumbersOnly)).Text = variable.DefaultValue
                        Case GetType(Int16)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.Int16BoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.NumbersOnly)).Text = variable.DefaultValue
                        Case GetType(Date), GetType(DateTime), GetType(TimeSpan), GetType(DateTimeOffset)
                            AddTextbox(variableNameWithoutAt, gp, rowNumber, New TextChangedEventHandler(AddressOf ParseCheck.DateBoundsCheck), New TextCompositionEventHandler(AddressOf InputFilters.DateCharactersOnly)).Text = variable.DefaultValue
                        Case GetType(Byte())
                            Dim input As New Button
                            input.Content = "Browse"
                            input.Name = variableNameWithoutAt
                            input.VerticalAlignment = Windows.VerticalAlignment.Center
                            input.MaxWidth = 100
                            If Not String.IsNullOrEmpty(variable.UIAttribute.AttributeData) AndAlso variable.UIAttribute.AttributeType = UIAttributeEnumeration.FileFilter Then
                                UIMetaData(variableNameWithoutAt).add(New KeyValuePair(Of String, Object)("filefilter", variable.UIAttribute.AttributeData))
                            End If
                            AddHandler input.Click, Sub(s, ev)
                                                        Dim btn As Button = s

                                                        Dim dlg As New OpenFileDialog
                                                        Dim meta As List(Of KeyValuePair(Of String, Object)) = UIMetaData(s.Name)
                                                        Dim filter As String = (From e In meta Where e.Key = "filefilter" Select e.Value).FirstOrDefault()
                                                        If Not String.IsNullOrEmpty(filter) Then
                                                            dlg.Filter = filter
                                                        End If

                                                        If dlg.ShowDialog Then
                                                            Dim filecontents As Byte() = IO.File.ReadAllBytes(dlg.FileName)
                                                            meta.RemoveAll(Function(e) e.Key = "filecontents")
                                                            meta.Add(New KeyValuePair(Of String, Object)("filecontents", filecontents))
                                                            UIMetaData.Remove(s.Name)
                                                            UIMetaData.Add(s.Name, meta)
                                                            btn.Background = Brushes.LightGreen
                                                        End If
                                                    End Sub

                            Grid.SetColumn(input, 1)
                            Grid.SetRow(input, rowNumber)
                            gp.Children.Add(input)
                            QueryForm.RegisterName(input.Name, input)
                        Case GetType(Boolean)
                            Dim input As New CheckBox
                            input.Name = variableNameWithoutAt
                            input.VerticalAlignment = Windows.VerticalAlignment.Center
                            Grid.SetColumn(input, 1)
                            Grid.SetRow(input, rowNumber)
                            gp.Children.Add(input)
                            QueryForm.RegisterName(input.Name, input)
                        Case Else
                            AddTextbox(variableNameWithoutAt, gp, rowNumber)
                    End Select
            End Select
        Next
    End Sub

    Private Sub AddTextbox(ByVal name As String, ByRef gp As Grid, ByVal rowNumber As Integer)
        AddTextbox(name, gp, rowNumber, Nothing, Nothing)
    End Sub

    Private Function AddTextbox(ByVal name As String, ByRef gp As Grid, ByVal rowNumber As Integer, ByRef boundsCheck As TextChangedEventHandler, ByRef inputCheck As TextCompositionEventHandler) As TextBox
        Dim input As New TextBox
        If Not IsNothing(boundsCheck) Then
            AddHandler input.TextChanged, boundsCheck
        End If

        If Not IsNothing(inputCheck) Then
            AddHandler input.PreviewTextInput, inputCheck
        End If

        input.Name = name
        input.VerticalAlignment = Windows.VerticalAlignment.Center
        input.Margin = New Thickness(0, 0, 5, 0)
        Grid.SetColumn(input, 1)
        Grid.SetRow(input, rowNumber)
        gp.Children.Add(input)
        QueryForm.RegisterName(input.Name, input)
        Return input
    End Function

    Private Sub ClearDynamicForm()
        Dim queryFormGrid As Grid = QueryForm.Children(0)
        For Each e As FrameworkElement In queryFormGrid.Children
            If Not String.IsNullOrEmpty(e.Name) Then QueryForm.UnregisterName(e.Name)
        Next
        QueryForm.Children.Clear()
        UIMetaData.Clear()
    End Sub

    Private Sub NewQuery_Click(sender As Object, e As RoutedEventArgs)
        Dim qe As New QueryEditor
        Dim dialogResult As Boolean = False

        If Not IsNothing(connectionList.SelectedItem) Then
            dialogResult = qe.ShowDialog(connectionList.SelectedItem.Contents)
        Else
            dialogResult = qe.ShowDialog()
        End If
    End Sub

    Private Sub Exit_Click(sender As Object, e As RoutedEventArgs)
        Environment.Exit(0)
    End Sub

    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Dim connectionListSource As New ObservableCollection(Of Entity)(connections.Entities.ToArray)
        Dim queryListSource As New ObservableCollection(Of Entity)(querys.Entities.ToArray)

        queryList.ItemsSource = queryListSource
        connectionList.ItemsSource = connectionListSource
    End Sub
End Class
